/**
 * Tree item control. Tree item can be included into a tree control as a child,
 * and can also have child items, either tree items or any other controls.
 *
 * @author Andrey Anisimov <hercules@inbox.ru>
 */

import core.ui.FocusWindow;

class TreeItem extends FocusWindow {
	
	/**
	 * Creates new tree item control.
	 * 
	 * @param parent (Window) [optional] parent window
	 * @param x, y (int) [optional] coordinates
	 * @param width, height (int) [optional] control size.
	 */
	this.TreeItem = function(parent, x, y, width, height) {
		super(parent, x, y, width, height);
		this.state = false;
		this.selected = false;
		this.items = [];
		this.addStyleName(this.getStyleName() + '-leaf');
		this.attach(this.text);
	}

	/**
	 * Sets whether the child items are displayed.
	 *
	 * @param state (bool) true to display child items, false otherwise.
	 */
	this.setState = function(state) {
		this.state = state;
		if (state) {
			this.addStyleName(this.getStyleName() + '-expanded');
		} else {
			this.removeStyleName(this.getStyleName() + '-expanded');
		}
		if (this.subtree) {
			this.subtree.style.display = (state) ? 'block' : 'none';
		}
	}
	
	/**
	 * Gets whether the child items are displayed.
	 *
	 * @return bool.
	 */
	this.getState = function() {
		return this.state;
	}
	
	/**
	 * Sets whether the item is selected.
	 *
	 * @param selected (bool) selected value
	 */
	this.setSelected = function(selected) {
		this.selected = selected;
		if (selected) {
			this.addStyleName(this.getStyleName() + '-selected');
		} else {
			this.removeStyleName(this.getStyleName() + '-selected');
		}
	}
	
	/**
	 * Gets whether the item is selected.
	 *
	 * @return bool
	 */
	this.isSelected = function() {
		return this.selected;
	}
	
	/**
	 * Adds new child item.
	 *
	 * @param item (Window) new item.
	 */
	this.addItem = function(item) {
		this.items.push(item);
		this.removeStyleName(this.getStyleName() + '-leaf');
		this.addStyleName(this.getStyleName() + '-branch');
		return item;
	}

	/**
	 * Gets the child item with specified index.
	 *
	 * @param i (int) item index.
	 */
	this.getItem = function(i) {
		return this.items[i];
	}
	
	/**
	 * Gets count of child items.
	 *
	 * @return int
	 */
	this.getItemCount = function(i) {
		return this.items.length;
	}
	
	/**
	 * Checks whether the item is leaf.
	 *
	 * @return bool
	 */
	this.isLeaf = function() {
		return (0 == this.getItemCount());
	}
	
	/**
	 * Checks whether the item is branch.
	 *
	 * @return bool
	 */
	this.isBranch = function() {
		return !this.isLeaf();
	}
	
	/**
	 * Removes child item with specified index.
	 *
	 * @param i (int) child item index.
	 */
	this.removeItem = function(i) {
		
		this.items[i].close();
		delete this.items[i];
		this.items.splice(i, 1);

		if (this.isLeaf()) {
			this.removeSubtree();
			this.removeStyleName(this.getStyleName() + '-branch');
			this.addStyleName(this.getStyleName() + '-leaf');
		}
	}

	/**
	 * Removes all child items.
	 */
	this.removeItems = function() {
		while (this.items.length > 0) {
			var item = this.items.pop();
			item.close();
			delete item;
		}
		this.removeSubtree();
		this.removeStyleName(this.getStyleName() + '-branch');
		this.addStyleName(this.getStyleName() + '-leaf');
	}
	
	/**
	 * Return item index. For removeItem(), for example.
	 */
	this.getItemIndexById = function(id) {
		for (var i=0; i < this.items.length; i++) {
			if (this.items[i].getId() == id) {
				return i;
			}
		}
		return false;
	}

	this.close = function() {
		this.detach(this.text);
		this.getElement().removeChild(this.text);
		delete this.text;
		this.removeSubtree();
		super.close();
	}
	
	this.setText = function(text) {
		this.text.innerHTML = text;
	}
	
	this.getText = function() {
		return this.text.innerHTML;
	}

	/**
 	 * @protected
 	 * Creates child subtree element.
	 */
	this.createSubtree = function() {
		this.subtree = document.createElement('div');
		this.subtree.style.display = 'none';
		this.subtree.className = 'SubTree';
		var el = this.getElement();
		if (el.nextSibling) {
			el.parentNode.insertBefore(this.subtree, el.nextSibling);
		} else {
			el.parentNode.appendChild(this.subtree);
		}
	}
	
	/**
	 * @protected
	 * Removes subtree element.
	 */
	this.removeSubtree = function() {
		if (this.subtree) {
			this.subtree.parentNode.removeChild(this.subtree);
			delete this.subtree;
		}
	}
	
	/**
	 * @protected
	 * Creates and returns root element for the tree item.
	 *
	 * @return HTMLElement
	 */
	this.createElement = function() {
		var root = super.createElement();
		this.text = document.createElement('span');
		this.text.className = 'TreeItemText';
		root.appendChild(this.text);
		
		/*with (core.ui.quirks.TextSelection) {
			preventSelection(root);
			preventSelection(this.text);
		}*/
		
		return root;
	}

	/**
	 * @protected
	 * Adds new child element.
	 * 
	 * @param child (HTMLElement) element to add
	 */
	this.addElement = function(child) {
		if (!this.subtree) this.createSubtree();
		this.subtree.appendChild(child);
	}
}